﻿/*
 *
 *	C# object representation of row in 'researchRepo.files' table:
 *	
 *	Permissions are handled by storing both the public permission type for the file and the user's apparent permission type. Since public permissions
 *	are the minimum permissions for each file, public permissions may override the user permissions given to a constructor.
 *	
 *	Each RRFile is a node within a doubly-linked tree of RRFiles. Every file (except the repo root) stores a pointer to its parent directory (parent node);
 *	if a file is a directory then it stores a List of sub files (child nodes). The superDirID property is thus redundant and is not stored.
 *	
 *	All other properties map directly from table columns to equivalent properties.
 *	
 *	TODO Currently tree-related properties are public, but should probably be wrapped with some reference-swapping functionality to allow nodes to
 *	automatically maintain integrity of tree structure:
 *		SuperDir - set: remove 'this' from old this.SuperDir.SubFiles and add 'this' to new this.SuperDir.SubFiles
 *		SubFiles - hide List and instead implement AddSubFile(RRFile sub), UpdateSubFile(int index, RRfile sub), and RemoveSubFile(int index) which each
 *					update sub.SuperDir appropriately
 *
 */

using System;
using System.Linq;
using System.Collections.Generic;
using MySql.Data.Types;

namespace ResearchRepository.Models
{
	public class RRFile
	{
		public RRFile(int fID, /*int superFID,*/ string fName, bool isD, MySqlDateTime dCreated, int cID, MySqlDateTime dModified, int mID,		// DB table properties
						RRPermissionType uPerm, RRPermissionType pPerm, RRFile superD = null, IEnumerable<RRFile> subF = null)					// additional permissions and doubly-linked tree properties
		{
			FileID = fID;
			/*SuperDirID = superFID;*/
			FileName = fName;
			IsDir = isD;
			DateCreated = dCreated;
			CreatorId = cID;
			DateModified = dModified;
			ModifierId = mID;
			UserPermission = uPerm >= pPerm ? uPerm : pPerm;	// public permission is minimum permission level, so if given user permission is less than public then use public
			PublicPermission = pPerm;
			SuperDir = superD;
			SubFiles = IsDir ? subF == null ? new List<RRFile>() : new List<RRFile>(subF) : null;
		}
		public RRFile(RRFile source)
			:this(source.FileID,
					/*source.SuperDirID,*/
					source.FileName,
					source.IsDir,
					source.DateCreated,
					source.CreatorId,
					source.DateModified,
					source.ModifierId,
					source.UserPermission,
					source.PublicPermission,
					source.SuperDir,
					source.SubFiles)
		{}
		public RRFile(System.Data.IDataRecord source, RRFile superD = null, IEnumerable<RRFile> subF = null)
			:this((int) source["fileID"],
					/*(int) source["superDirID"],*/
					(string) source["fileName"],
					((UInt64) source["isDir"]) == 1,
					(MySqlDateTime) source["dateCreated"],
					(int) source["creatorID"],
					(MySqlDateTime) source["dateModified"],
					(int) source["modifierID"],
					(RRPermissionType) Enum.Parse(typeof(RRPermissionType), source["userPermName"] != System.DBNull.Value ? (string) source["userPermName"]			// if userPermName is NULL, then user is 'guest', so use public permissions
																															: (string) source["publicPermName"]),
					(RRPermissionType) Enum.Parse(typeof(RRPermissionType), (string) source["publicPermName"]),
					superD,
					subF)
		{}

		// named alias for constructor, provides handle to simulate a function pointer to constructor
		public static RRFile construct(System.Data.IDataRecord source)
		{
			return new RRFile(source);
		}
		// provide generic instance of repo root as seed to populate file tree
		public static RRFile EmptyRoot
		{
			get
			{
				return new RRFile(-1, /*-1,*/ "", true, new MySqlDateTime(), 0, new MySqlDateTime(), 0, RRPermissionType.view, RRPermissionType.view);
			}
		}

		public int FileID { get; set; }
		//public int SuperDirID { get; set; }
		public string FileName { get; set; }
		public bool IsDir { get; set; }
		public MySqlDateTime DateCreated { get; set; }
		public int CreatorId { get; set; }
		public MySqlDateTime DateModified { get; set; }
		public int ModifierId { get; set; }
		public RRPermissionType UserPermission { get; set; }
		public RRPermissionType PublicPermission { get; set; }
		public RRFile SuperDir { get; set; }			// TODO tree management
		public List<RRFile> SubFiles { get; set; }		// TODO tree management
	}
}